<?php

namespace Framework\Foundation\Route;

// 原生写法
//$r->addGroup('/admin', function (RouteCollector $r) {
//    $r->addRoute('GET', '/do-something', 'handler');
//    $r->addRoute('GET', '/do-another-thing', 'handler');
//    $r->addRoute('GET', '/do-something-else', 'handler');
//});
//* @method static addRoute($httpMethod, $route, $handler)
//* @method static get($route, $handler)
//* @method static post($route, $handler)
//* @method static put($route, $handler)
//* @method static delete($route, $handler)
//* @method static patch($route, $handler)
//* @method static head($route, $handler)
//* @method static array getData()
use FastRoute\RouteCollector;
use FastRoute\Dispatcher\GroupCountBased;

/**
 * Class Router
 * @package Framework\Foundation\Route
 *
 *
 */
class Router
{
    public static $stackTop = -1; // 默认空栈
    public static $groupStack = [];

    /**
     * @var RouteCollector
     */
    public static $routeCollector;


    public static function initRouteCollector($routeCollector = null)
    {
        if (!is_null($routeCollector)) {
            self::$routeCollector = $routeCollector;
            return;
        }

        $assistant = new RouterFactory();
        self::$routeCollector = $assistant->getRouteCollector();
    }

    public static function getDispatcher()
    {
        return new GroupCountBased(self::$routeCollector->getData());
    }

    public static function groupStart($prefix = '', $options = [])
    {
        if (self::$stackTop == -1) {
            self::$groupStack[0] = [
                'prefix' => $prefix,
                'options' => $options
            ];

            self::$stackTop = 0;
        } else {
            $previousLevel = self::$stackTop;
            $previousGroupPrefix = self::$groupStack[$previousLevel]['prefix'];
            $previousGroupOptions = self::$groupStack[$previousLevel]['options'];

            self::$stackTop++;
            self::$groupStack[self::$stackTop] = [
                'prefix' => $previousGroupPrefix . $prefix,
                'options' => array_merge_recursive($previousGroupOptions, $options)
            ];
        }
    }


    public static function groupStop()
    {
        if (self::$stackTop < 0) {
            return;
        }
        unset(self::$groupStack[self::$stackTop]);
        self::$stackTop--;
    }

    public static function addRoute($method, $route, $handler, $options = [])
    {
        $joinGroupRoute = self::getGroupPrefix() . $route;
        $mergeGroupOptions = array_merge_recursive(self::getGroupOptions(), $options);
        $mergeGroupOptions['action'] = $handler;

        self::$routeCollector->addRoute($method, $joinGroupRoute, $mergeGroupOptions);
    }

    public static function getGroupPrefix()
    {
        if (self::$stackTop == -1) {
            return '';
        }

        return self::$groupStack[self::$stackTop]['prefix'];
    }

    public static function getGroupOptions()
    {
        if (self::$stackTop == -1) {
            return [];
        }

        return self::$groupStack[self::$stackTop]['options'];
    }

    public static function get($route, $handler, $options = [])
    {
        self::addRoute('GET', $route, $handler, $options);
    }

    public static function post($route, $handler, $options = [])
    {
        self::addRoute('POST', $route, $handler, $options);
    }

    public static function put($route, $handler, $options = [])
    {
        self::addRoute('PUT', $route, $handler, $options);
    }

    public static function delete($route, $handler, $options = [])
    {
        self::addRoute('DELETE', $route, $handler, $options);
    }

    public static function patch($route, $handler, $options = [])
    {
        self::addRoute('PATCH', $route, $handler, $options);
    }

    public static function head($route, $handler, $options = [])
    {
        self::addRoute('HEAD', $route, $handler, $options);
    }

    public static function any($route, $handler, $options = [])
    {
        self::addRoute(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD'], $route, $handler, $options);
    }

    public static function gpp($route, $handler, $options = [])
    {
        self::addRoute(['GET', 'POST', 'PUT'], $route, $handler, $options);
    }

    public static function rest($route, $handler, $options = [])
    {
        self::addRoute(['GET', 'POST', 'PUT', 'DELETE'], $route, $handler, $options);
    }


    public static function getRouteCollector()
    {
        return self::$routeCollector;
    }
}
